evaluate.c
Overview
evaluate.c is a piece of documented example code showing an
interesting and quick algorithim for evaluating algebraic strings, such as
"2 + 4" and "a=5; b=10; c=b-a; b*c". It is released under
the GNU General Public License version 2 or later.
Purpose
Mainly so I can write a new calculus.library for the Amiga, but
to be honest, I'd like programmers who write evaluators to take a look at
it and maybe learn something. I've used many evaluators, and often there
are terrible mistakes. My pet peeves are:
- Using a full regexp scanner and LALR parser!
- No operator precedence!
- Only evaluating with integer arithmetic.
- Having fixed number of variables or fixed variable name lengths.
- Having some arbitrary limit on the evaluation depth or number of tokens.
Usage
Call this function:
int Calculate(char *string, long *intres, double *realres, int *error);
Its arguments are:
- string is an expression to evaluate.
- intres is a pointer to a long, which after evaluation
will contain an integer form of the result. It can be NULL if you
don't want to recieve an integer result.
- realres is a pointer to a double, which after
evaluation will contain a real form of the result. It can be NULL
if you don't want to recieve a real result.
- error is a pointer to an int that will hold the error
code - see evaluate.h for a list. It can be NULL if you
don't want to recieve an error code.
The value returned by the function is an int, and is either
RESULT_INTEGER or RESULT_REAL. This reveals what final
type the evaluation had, however both intres and realres
are always filled out correctly.
Read about how the code works
.
To compile the example eval.c:
- for gcc type: gcc -s -o eval eval.c evaluate.c -lm
- for vbcc 68000 type: vc -sc -o eval eval.c evaluate.c
vlib:mieee.lib
- for vbcc 020/FPU type: vc -sc -cpu=68020 -fpu=68881 -o
eval eval.c evaluate.c vlib:m881.lib
Expressions
You can follow any expression with a semicolon and another expression. The
expression is a mixture of values, variables and operators, in infix
notation. You can use parentheses (round brackets) to force a particular
order. The operators are as follows:
+ | addition | << | bitwise shift left |
- | subtraction (or negation) | >> | bitwise shift right |
* | multiplication | && | logical and |
/ | division | || | logical or |
** | raise to the power | ! | logical not |
% | modulus | == | equality test |
= | assignment | != | inequality test |
& | bitwise AND | < | less than test |
| | bitwise OR | > | greater than test |
~ | bitwise NOT | <= | less than or equal to test |
^ | bitwise XOR | >= | greater than or equal to test |
The precedence of the operators is as follows, from highest (most tightly
binding) to lowest:
- implicit multiplication
- !, ~, unary -
- **
- *, /, %
- +, -
- <<, >>
- <, >, <=, >=
- ==, !=
- &,
- |, ^
- &&, ||
- =
- functions
The available functions are acos, asin, atan,
cos, cosh, exp, ln, log,
sin, sinh, sqr, sqrt, tan and
tanh. All functions take one argument. You do not need to have
parentheses round the argument.
Any text other than function is considered to be a variable reference. The
only default variable is pi, which is defined as "4 * atan
1", all others have to be assigned in the expression before use (for
example, "a=5; b=a-3; a+b"), or set as operating system
environment variables.
The behaviour of operators and functions, and the accuracy of results is
entirely down to the C compiler which compiles evaluate.c.
Kyzer/CSG